﻿using jvm.classfile.attributeinfo;
using jvm.rtda.heap.clazz.cp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.rtda.heap.clazz.method
{
    class ExceptionHandler
    {
        public int startPc;
        public int endPc;
        public int handlerPc;
        public ClassRef catchType;
    }

    class ExceptionTable
    {
        public ExceptionHandler[] handlers;

        public ExceptionTable(ExceptionTableEntry[] entries, JConstantPool pool)
        {
            handlers = new ExceptionHandler[entries.Length];
            for (int i = 0; i < handlers.Length; i++)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.startPc = entries[i].startPc;
                handler.endPc = entries[i].endPc;
                handler.handlerPc = entries[i].handlerPc;
                handler.catchType = GetCatchType(entries[i].catchType, pool);
                handlers[i] = handler;
            }
        }

        ClassRef GetCatchType(ushort catchType, JConstantPool pool)
        {
            if (catchType == 0)
            {
                return null;
            }
            return pool.GetConstant<ClassRef>(catchType);
        }

        public ExceptionHandler FindExceptionHandler(JClass exceptionClass, int pc)
        {
            foreach (ExceptionHandler handler in handlers)
            {
                if (pc >= handler.startPc && pc < handler.endPc)
                {
                    if (handler.catchType == null)
                    {
                        return handler;
                    }
                    JClass catchClass = handler.catchType.ResolvedClass();
                    if (catchClass == exceptionClass || catchClass.IsSuperClassOf(exceptionClass))
                    {
                        return handler;
                    }
                }
            }
            return null;
        }
    }
}
